package flowdroid.taint;

import flowdroid.algo.ReverseDFS;
import flowdroid.algo.ReverseDFSImpl;
import pojo.MethodMarks;
import pojo.MyDataFlowResult;
import pojo.MyTuple;
import soot.SootClass;
import soot.SootMethod;
import tuple.TupleManager;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;


public class ResultTupleCreator {
    private final ReverseDFS reverseDFS;

    ResultTupleCreator() throws IOException {
        reverseDFS = new ReverseDFSImpl();
    }

    // 这是一个模板方法(Template method)
    @Nullable
    public MyTuple apply(@Nonnull MyDataFlowResult result) {
        Set<SootMethod> methods = new HashSet<>(result.getMethodList());

        for (SootMethod sootMethod : methods) {
            SootClass sootClass = sootMethod.getDeclaringClass();
            MethodMarks methodMarks = new MethodMarks();
            try {
                // 1. 以【类】的粒度检查: 包名类名, 字段, 构造器和静态构造器(注意构造器和静态构造器都依赖于 checkMethodBody,不检查它们的参数
                reverseDFS.checkSootClass(sootClass, methodMarks, 0);

                // 2. 从【方法体】的角度检查
                reverseDFS.checkMethod(sootMethod, methodMarks, 0);

                // 3. check Edge
            } catch (Exception ignored) {
            }
            result.getDataSet().addAll(methodMarks.dataKinds);
            result.getEntitySet().addAll(methodMarks.entitySet);
            result.getPermission().addAll(methodMarks.stringMarks);
        }
        return TupleManager.createMyTuple(result.getEntitySet(), result.getDataSet(), result.getPermission());
    }
}
